/*
 * ScriptStructure.c
 * VB Script Analyzer
 * @author Gregoire JACOB (gregoire.jacob@orange-ftgroup.com)
 * @date 27/08/2008
 * @version 1.1
 */

#include ".\Includes\Analyzer.h"

/** Begin Structures update and printings **************************************************/
void addManagerAlias(struct MANAG_ENTRY * managers, int type, char * alias){
	int nb;
	switch(type){
		case TFSO:
			nb = managers->nbfsoalias;
			managers->FileSystemAliases[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->FileSystemAliases[nb],NAME_MAX_LENGTH,alias);
			managers->nbfsoalias++;
			break;
		case TSHELL:
			nb = managers->nbshellalias;
			managers->ShellAliases[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->ShellAliases[nb],NAME_MAX_LENGTH,alias);
			managers->nbshellalias++;
			break;
		case TNETW:
			nb = managers->nbnetalias;
			managers->NetworkAliases[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->NetworkAliases[nb],NAME_MAX_LENGTH,alias);
			managers->nbnetalias++;
			break;
		case TMAIL:
			nb = managers->nbmailalias;
			managers->MailAliases[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->MailAliases[nb],NAME_MAX_LENGTH,alias);
			managers->nbmailalias++;
			break;
	}
}

void addManagerObject(struct MANAG_ENTRY * managers, int type, char * object){
	int nb;
	switch(type){
		case TFSO:
			if(isFileManager(managers,object)>-1) return; //no duplicates
			nb = managers->nbfsoobj;
			managers->FileSystemObjects[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->FileSystemObjects[nb],NAME_MAX_LENGTH,object);
			managers->nbfsoobj++;
			break;
		case TSHELL:
			if(isShellManager(managers,object)>-1) return; //no duplicates
			nb = managers->nbshellobj;
			managers->ShellObjects[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->ShellObjects[nb],NAME_MAX_LENGTH,object);
			managers->nbshellobj++;
			break;
		case TNETW:
			if(isNetworkManager(managers,object)>-1) return; //no duplicates
			nb = managers->nbnetobj;
			managers->NetworkObjects[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->NetworkObjects[nb],NAME_MAX_LENGTH,object);
			managers->nbnetobj++;
			break;
		case TMAIL:
			if(isMailManager(managers,object)>-1) return; //no duplicates
			nb = managers->nbmailobj;
			managers->MailObjects[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->MailObjects[nb],NAME_MAX_LENGTH,object);
			managers->nbmailobj++;
			break;
		default:
			nb = managers->nbunknownobj;
			managers->UnknownManagers[nb] = (char *)calloc(NAME_MAX_LENGTH,sizeof(char));
			strcat_s(managers->UnknownManagers[nb],NAME_MAX_LENGTH,object);
			managers->nbunknownobj++;
	}
}

void printManagers(struct MANAG_ENTRY * managers){
	int i;
	if(managers->nbfsoobj||managers->nbshellobj||managers->nbnetobj||managers->nbmailobj)
		printf("Managers:\n");
	if(managers->nbfsoobj){
		printf("     | -FileSystemObjects:");
		for(i=0;i<managers->nbfsoobj;i++)
			printf(" %s",managers->FileSystemObjects[i]);
		if(managers->nbfsoalias){
			printf(" (Aliases:");
			for(i=0;i<managers->nbfsoalias;i++)
				printf(" %s",managers->FileSystemAliases[i]);
			printf(")");
		}
		printf("\n");
	}//if fso
	if(managers->nbshellobj){
		printf("     | -ShellObjects:");
		for(i=0;i<managers->nbshellobj;i++)
			printf(" %s",managers->ShellObjects[i]);
		if(managers->nbshellalias){
			printf(" (Aliases:");
			for(i=0;i<managers->nbfsoalias;i++)
				printf(" %s",managers->ShellAliases[i]);
			printf(")");
		}
		printf("\n");
	}//if shell
	if(managers->nbnetobj){
		printf("     | -NetworksObjects:");
		for(i=0;i<managers->nbnetobj;i++)
			printf(" %s",managers->NetworkObjects[i]);
		if(managers->nbnetalias){
			printf(" (Aliases:");
			for(i=0;i<managers->nbnetalias;i++)
				printf(" %s",managers->NetworkAliases[i]);
			printf(")");
		}
		printf("\n");
	}//if network
	if(managers->nbmailobj){
		printf("     | -MailOutlook:");
		for(i=0;i<managers->nbmailobj;i++)
			printf(" %s",managers->MailObjects[i]);
		if(managers->nbmailalias){
			printf(" (Aliases:");
			for(i=0;i<managers->nbmailalias;i++)
				printf(" %s",managers->MailAliases[i]);
			printf(")");
		}
		printf("\n");
	}//if mail
}

void printfManagers(FILE * f, struct MANAG_ENTRY * managers){
	int i;
	if(managers->nbfsoobj||managers->nbshellobj||managers->nbnetobj||managers->nbmailobj)
		fprintf(f,"Managers:\n");
	if(managers->nbfsoobj){
		fprintf(f,"     | -FileSystemObjects:");
		for(i=0;i<managers->nbfsoobj;i++)
			fprintf(f," %s",managers->FileSystemObjects[i]);
		if(managers->nbfsoalias){
			fprintf(f," (Aliases:");
			for(i=0;i<managers->nbfsoalias;i++)
				fprintf(f," %s",managers->FileSystemAliases[i]);
			fprintf(f,")");
		}
		fprintf(f,"\n");
	}//if fso
	if(managers->nbshellobj){
		fprintf(f,"     | -ShellObjects:");
		for(i=0;i<managers->nbshellobj;i++)
			fprintf(f," %s",managers->ShellObjects[i]);
		if(managers->nbshellalias){
			fprintf(f," (Aliases:");
			for(i=0;i<managers->nbfsoalias;i++)
				fprintf(f," %s",managers->ShellAliases[i]);
			fprintf(f,")");
		}
		fprintf(f,"\n");
	}//if shell
	if(managers->nbnetobj){
		fprintf(f,"     | -NetworksObjects:");
		for(i=0;i<managers->nbnetobj;i++)
			fprintf(f," %s",managers->NetworkObjects[i]);
		if(managers->nbnetalias){
			fprintf(f," (Aliases:");
			for(i=0;i<managers->nbnetalias;i++)
				fprintf(f," %s",managers->NetworkAliases[i]);
			fprintf(f,")");
		}
		fprintf(f,"\n");
	}//if network
	if(managers->nbmailobj){
		fprintf(f,"     | -MailOutlook:");
		for(i=0;i<managers->nbmailobj;i++)
			fprintf(f," %s",managers->MailObjects[i]);
		if(managers->nbmailalias){
			fprintf(f," (Aliases:");
			for(i=0;i<managers->nbmailalias;i++)
				fprintf(f," %s",managers->MailAliases[i]);
			fprintf(f,")");
		}
		fprintf(f,"\n");
	}//if mail
}

void printLine(struct LINE * line){
	char * type[8] = {"UNTYPED","COMMENT","MARKUPS","VDECLAR",
			"MANAGER","LOCCALL","SYSCALL","VAFFECT"};
	printf("[%s] %s",type[line->type],line->line);
}

void printfLine(FILE * f, struct LINE * line){
	char * type[8] = {"UNTYPED","COMMENT","MARKUPS","VDECLAR",
			"MANAGER","LOCCALL","SYSCALL","VAFFECT"};
	fprintf(f,"[%s] %s",type[line->type],line->line);
}

void printFunction(struct FUNC_ENTRY * function){
	int i;

	printf("[+] Function %s\n",function->name);
	if(function->nbarg){
		printf("Arguments:\n");
		for(i=0;i<function->nbarg;i++)
			printf("     | -%s\n",function->arguments[i]);
	}//if arguments
	if(function->nbvar){
		printf("Variables:\n");
		for(i=0;i<function->nbvar;i++)
			printf("     | -%s\n",function->variables[i]);
	}//if variables
	printManagers(&function->managers);
	printf("Position:\n     | -%d to %d\n",function->begin,function->end);
	printf("Code:\n     | -from position %d\n     | -%d lines of code\n",
		   function->codepos,function->nblines);
	printf("[+] End Function\n");
}

void printfFunction(FILE * f, struct FUNC_ENTRY * function){
	int i;

	fprintf(f,"[+] Function %s\n",function->name);
	if(function->nbarg){
		fprintf(f,"Arguments:\n");
		for(i=0;i<function->nbarg;i++)
			fprintf(f,"     | -%s\n",function->arguments[i]);
	}//if arguments
	if(function->nbvar){
		fprintf(f,"Variables:\n");
		for(i=0;i<function->nbvar;i++)
			fprintf(f,"     | -%s\n",function->variables[i]);
	}//if variables
	printfManagers(f,&function->managers);
	fprintf(f,"Position:\n     | -%d to %d\n",function->begin,function->end);
	fprintf(f,"Code:\n     | -from position %d\n     | -%d lines of code\n",
		   function->codepos,function->nblines);
	fprintf(f,"[+] End Function\n");
}

void printProcedure(struct PROC_ENTRY * procedure){
	int i;

	printf("[+] Procedure %s\n",procedure->name);
	if(procedure->nbarg){
		printf("Arguments:\n");
		for(i=0;i<procedure->nbarg;i++)
			printf("     | -%s\n",procedure->arguments[i]);
	}//if arguments
	if(procedure->nbvar){
		printf("Variables:\n");
		for(i=0;i<procedure->nbvar;i++)
			printf("     | -%s\n",procedure->variables[i]);
	}//if variables
	printManagers(&procedure->managers);
	printf("Position:\n     | -%d to %d\n",procedure->begin,procedure->end);
	printf("Code:\n     | -from position %d\n     | -%d lines of code\n",
		   procedure->codepos,procedure->nblines);
	printf("[+] End Procedure\n");
}

void printfProcedure(FILE * f, struct PROC_ENTRY * procedure){
	int i;

	fprintf(f,"[+] Procedure %s\n",procedure->name);
	if(procedure->nbarg){
		fprintf(f,"Arguments:\n");
		for(i=0;i<procedure->nbarg;i++)
			fprintf(f,"     | -%s\n",procedure->arguments[i]);
	}//if arguments
	if(procedure->nbvar){
		fprintf(f,"Variables:\n");
		for(i=0;i<procedure->nbvar;i++)
			fprintf(f,"     | -%s\n",procedure->variables[i]);
	}//if variables
	printfManagers(f,&procedure->managers);
	fprintf(f,"Position:\n     | -%d to %d\n",procedure->begin,procedure->end);
	fprintf(f,"Code:\n     | -from position %d\n     | -%d lines of code\n",
		   procedure->codepos,procedure->nblines);
	fprintf(f,"[+] End Procedure\n");
}

void printScript(struct SCRIPT * script){
	int i;

	printf("\\** Script: %s *************************************/\n",script->name);
	printf("[+] Global variables:\n");
	if(script->nbvar){
		for(i=0;i<script->nbvar;i++)
			printf("     | -%s\n",script->variables[i]);
		printf("\n");
	}//if global variable
	printManagers(&script->managers);
	printf("\n");
	printf("[+] Code:\n     | -%d lines of code\n",script->nblines);
	printf("[+] Script Functions:\n");
	for(i=0;i<script->nbfunc;i++){
		printf("------------------------\n");
		printFunction(&script->functionslist[i]);
	}
	printf("------------------------\n");
	printf("\n");
	printf("[+] Script Procedures:\n");
	for(i=0;i<script->nbproc;i++){
		printf("------------------------\n");
		printProcedure(&script->procedureslist[i]);
	}
	printf("------------------------\n");
	printf("\n");
	if(script->strciphered){
		printf("[+] String ciphered by %s\n\n",
			script->functionslist[script->cipherfunction].name);
	}
	printf("\\** End Script: %s *********************************/\n\n\n",script->name);
}

void printfScript(FILE * f, struct SCRIPT * script){
	int i;

	fprintf(f,"\\** Script: %s *************************************/\n",script->name);
	fprintf(f,"Global variables:\n");
	if(script->nbvar){
		for(i=0;i<script->nbvar;i++)
			fprintf(f,"     | -%s\n",script->variables[i]);
		//fprintf(f,"\n");
	}//if global variable
	printfManagers(f,&script->managers);
	//fprintf(f,"\n");
	fprintf(f,"Code:\n     | -%d lines of code\n",script->nblines);
	fprintf(f,"Script Functions:\n");
	for(i=0;i<script->nbfunc;i++){
		fprintf(f,"------------------------\n");
		printfFunction(f,&script->functionslist[i]);
	}
	fprintf(f,"------------------------\n");
	fprintf(f,"\n");
	fprintf(f,"Script Procedures:\n");
	for(i=0;i<script->nbproc;i++){
		fprintf(f,"------------------------\n");
		printfProcedure(f,&script->procedureslist[i]);
	}
	fprintf(f,"------------------------\n");
	fprintf(f,"\n");
	if(script->strciphered){
		fprintf(f,"[+] String ciphered by %s\n\n",
			script->functionslist[script->cipherfunction].name);
	}
	fprintf(f,"\\** End Script: %s *********************************/\n\n\n",script->name);
}
/** End Structures update and printings ****************************************************/

/** Begin Existence tests on structures ****************************************************/
int insideFunction(struct SCRIPT * script, int position){
	int i;
	for(i=0;i<script->nbfunc;i++){
		if(position>=script->functionslist[i].begin 
			&& position<=script->functionslist[i].end){
				return 1;
		}
	}
	return 0;
}

int insideProcedure(struct SCRIPT * script, int position){
	int i;
	for(i=0;i<script->nbproc;i++){
		if(position>=script->procedureslist[i].begin 
			&& position<=script->procedureslist[i].end){
				return 1;
		}
	}
	return 0;
}

int recoverMaximalPosition(struct SCRIPT * script, unsigned long location){
	switch(location&0xF0000000){
		case MAINLEVEL:
			return script->nblines; 
		case FUNCLEVEL:
			return script->functionslist[location&0x0FFFFFFF].nblines;
		case PROCLEVEL:
			return script->procedureslist[location&0x0FFFFFFF].nblines;
	}//switch
	printf("[-] Invalid location: neither main, function or procedure\n");
	return 0;
}

int isFileManager(struct MANAG_ENTRY * managers, char *  token){
	int i;

	for(i=0;i<managers->nbfsoobj;i++){
		if(!strcasecmp(token,managers->FileSystemObjects[i])) return 1;
	}
	return -1;
}

int isShellManager(struct MANAG_ENTRY * managers, char *  token){
	int i;

	for(i=0;i<managers->nbshellobj;i++){
		if(!strcasecmp(token,managers->ShellObjects[i])) return 1;
	}
	return -1;
}

int isNetworkManager(struct MANAG_ENTRY * managers, char *  token){
	int i;

	for(i=0;i<managers->nbnetobj;i++){
		if(!strcasecmp(token,managers->NetworkObjects[i])) return 1;
	}
	return -1;
}

int isMailManager(struct MANAG_ENTRY * managers, char *  token){
	int i;

	for(i=0;i<managers->nbmailobj;i++){
		if(!strcasecmp(token,managers->MailObjects[i])) return 1;
	}
	return -1;
}

int isUnknownManager(struct MANAG_ENTRY * managers, char *  token){
	int i;

	for(i=0;i<managers->nbunknownobj;i++){
		if(!strcasecmp(token,managers->UnknownManagers[i])) return 1;
	}
	return -1;
}

int isLocalFunction(struct SCRIPT * script, char *  token){
	int i;

	for(i=0;i<script->nbfunc;i++){
		if(!strcasecmp(token,script->functionslist[i].name)) return i;
	}
	return -1;
}

int isLocalProcedure(struct SCRIPT * script, char *  token){
	int i;

	for(i=0;i<script->nbproc;i++){
		if(!strcasecmp(token,script->procedureslist[i].name)) return i;
	}
	return -1;
}

int isStaticScriptObject(char * token){
	return !strcasecmp(token,"WScript");
}
/** End Existence tests on structures ******************************************************/

/** Begin Access to structures *************************************************************/
struct LINE * accessLine(struct SCRIPT * script, unsigned long location, int lineindex){
	//Access line according to its location
	switch(location&0xF0000000){
		case MAINLEVEL:
			return &(script->code[lineindex]);
		case FUNCLEVEL:
			return &(script->functionslist[location&0x0FFFFFFF].code[lineindex]);
		case PROCLEVEL:
			return &(script->procedureslist[location&0x0FFFFFFF].code[lineindex]);
		default:
			printf("[-] Invalid location (other than main, function or procedure\n");
	}//switch
	return NULL;
}

struct MANAG_ENTRY * accessManagers(struct SCRIPT * script, unsigned long location){
	//Access line according to its location
	switch(location&0xF0000000){
		case MAINLEVEL:
			return &(script->managers);
		case FUNCLEVEL:
			return &(script->functionslist[location&0x0FFFFFFF].managers);
		case PROCLEVEL:
			return &(script->procedureslist[location&0x0FFFFFFF].managers);
		default:
			printf("[-] Invalid location (other than main, function or procedure\n");
	}//switch
	return NULL;
}
/** End Access to structures ***************************************************************/






	